package com.example.jmxdemo.jmx;

import javax.management.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 动态 MBean：
 * <p>
 * 动态 MBean 允许在运行时动态地改变其属性和操作，而不需要预先定义所有的管理接口。
 * 动态 MBean 实现了 DynamicMBean 接口，该接口提供了方法来动态地获取 MBean 的元数据信息、属性值和执行操作。
 * 动态 MBean 适用于需要动态扩展或在运行时决定其属性和操作的情况。
 */
public class HelloDynamicMBean implements DynamicMBean {

    public static final String name = "MyDynamicMBean";

    private Map<String, Object> attributes = new HashMap<>();
    private String message = "MyDynamicMBean message";

    @Override
    public MBeanInfo getMBeanInfo() {
        MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[attributes.size() + 1];
        int i = 0;
        for (Map.Entry<String, Object> entry : attributes.entrySet()) {
            String attrName = entry.getKey();
            Object attrValue = entry.getValue();
            Class<?> attrType = attrValue.getClass();
            attrs[i++] = new MBeanAttributeInfo(attrName, attrType.getName(), "Attribute " + attrName, true, true, false);
        }
        attrs[i] = new MBeanAttributeInfo("message", "java.lang.String", "Attribute message", true, true, false);
        MBeanOperationInfo[] ops = new MBeanOperationInfo[1];
        ops[0] = new MBeanOperationInfo("sayHello", "Say hello to the world", null, "void", MBeanOperationInfo.ACTION);
        return new MBeanInfo(this.getClass().getName(), "My Dynamic MBean", attrs, null, ops, null);
    }

    @Override
    public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
        Object value = attributes.get(attribute);
        if (value == null) {
            throw new AttributeNotFoundException("No such attribute: " + attribute);
        }
        return value;
    }

    @Override
    public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        String name = attribute.getName();
        Object value = attribute.getValue();
        if (!attributes.containsKey(name)) {
            throw new AttributeNotFoundException("No such attribute: " + name);
        }
        attributes.put(name, value);
    }

    @Override
    public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
        if (actionName.equals("sayHello")) {
            System.out.println("Hello, world!");
        }
        return null;
    }

    @Override
    public AttributeList getAttributes(String[] attributes) {
        AttributeList list = new AttributeList();
        for (String attr : attributes) {
            try {
                Object value = getAttribute(attr);
                list.add(new Attribute(attr, value));
            } catch (Exception e) {
                // ignore
            }
        }
        return list;
    }

    @Override
    public AttributeList setAttributes(AttributeList list) {
        AttributeList result = new AttributeList();
        for (Object obj : list) {
            Attribute attr = (Attribute) obj;
            String name = attr.getName();
            Object value = attr.getValue();
            try {
                setAttribute(new Attribute(name, value));
                result.add(new Attribute(name, value));
            } catch (Exception e) {
                // ignore
            }
        }
        return result;
    }
}
